var cats_cache={};

var field_dictionaries;
function init_field_dictionaries(rr)
{
	if (field_dictionaries) return field_dictionaries;
	var fd=field_dictionaries={
		//field_datates:{},
		field_datatypes:{},
		field_groups: {},
		fields:{},
		field_groups_by_order: []
	};
	rr.site.models.MarketFieldDatatype.List().forEach(function(dt) {fd.field_datatypes[dt.id]=dt;});
	rr.site.models.MarketFieldGroup.List().forEach(function(dt) {fd.field_groups[dt.id]=dt;dt.fields=[];fd.field_groups_by_order.push(dt);});
	rr.site.models.MarketField.List().forEach(function(dt) {fd.fields[dt.id]=dt;fd.field_groups[dt.group_id].fields.push(dt);});
	return field_dictionaries;
}

function ins_upd(item_id,rr,tname,tcols,is_l10n)
{
	var sql_s="select 1 from "+tname+" where item_id=:item_id"+(is_l10n?" and l10n_id=:l10n_id":"");
	var sql_i1="item_id"+(is_l10n?",l10n_id":"");
	var sql_i2=":item_id"+(is_l10n?",:l10n_id":"");
	var sql_u="update "+tname+" set ";
	var i=0;
	for (var col in tcols) {
		if (i) sql_u+=",";
		sql_u+=col+"=:"+col;
		sql_i1+=","+col;
		sql_i2+=",:"+col;
		i++;
	}
	sql_u+=" where item_id=:item_id"+(is_l10n?" and l10n_id=:l10n_id":"");
	var sql_i="insert into "+tname+" ("+sql_i1+") values ("+sql_i2+")";

	function work(l10n_id)
	{	
		var h={item_id:item_id,l10n_id:l10n_id};
		for (var k in tcols) {
			if (!l10n_id) {h[k]=tcols[k];continue;}
			if (tcols[k][l10n_id]) {h[k]=tcols[k][l10n_id];continue;}
			for (var k2 in tcols[k]) if (!h[k]) h[k]=tcols[k][k2];
		}
		var test=rr.site.sql.execute_and_fetch_one_single(sql_s,h);
		if (test) {
			rr.site.sql.execute_single(sql_u,h);
		} else {
			rr.site.sql.execute_single(sql_i,h);
		}
	}
	if (is_l10n) {
	} else {
		work(0);
	}
}

function enum_decoder(rr,has_l10n,val)
{
	if (val=="" || val==undefined || val==null) return null;
	if (has_l10n==0) {
		var e=rr.site.models.MarketFieldEnum.Get(val);
		return e.value;
	} else {
		throw "TEMP";
	}
}

function enum_encoder(rr,has_l10n,val,field_id)
{
	if (val=="" || val==undefined || val==null) return null;
	if (has_l10n==0) {
		var e=rr.site.models.MarketFieldEnum.List("get_by_field_and_value",{value:val,field_id:field_id})[0];
		if (e) return e.id;
		var e=rr.site.models.MarketFieldEnum.Create();
		e.field_id=field_id;
		e.value=val;
		e.SaveAll();
		return e.id;
	} else {
		throw new Errror("TODO");
		var flag=false;
		for (var k in val.l10ns) if (!(val.l10ns[k]=="" || val.l10ns[k]==undefined || val.l10ns[k]==null)) flag=true;
		if (flag==false) return null;

	}
}

exports.add=[{
	 _type:"model_methods",
	_config: {name:"MarketItem"},

	/**
	 * Class: models.MarketItem
	 */

	/**
	 * Method: AfterFetchCustom
	 */
	AfterFetchCustom: function() {
		if (cats_cache[this.category_id]) {
			this.category_code=cats_cache[this.category_id];
			return;
		}
		var rr=this.GetRR();
		cats_cache[this.category_id]=this.category_code=rr.site.models.MarketCategory.Get(this.category_id).code;
	},

	/**
	 * Method: BeforeSaveCustom
	 */
	BeforeSaveCustom: function() {
		if (this.code) return;
		var rr=this.GetRR();
		var flag=false;
		var basecode=rr.F("Languages","to_code",this.l10ns[rr.site.default_l10n_id].name);
		var i=0;
		while (!flag) {
			this.code=basecode+(i?i:"");
			var mm=rr.site.models.MarketItem.List("get_by_code",{code:this.code});
			if (mm.length) {
				if (mm[0].id==this.id) flag=true; else i++;
			} else {
				flag=true;
			}
		}
	},

	/**
	 * Method: BeforeDeleteCustom
	 */
	BeforeDeleteCustom: function() {
		var rr=this.GetRR();
		rr.site.sql.execute_single("delete from tmarket_item_fields_enums where item_id=:item_id",{item_id:this.id});
		rr.site.sql.execute_single("delete from tmarket_item_fields_enumsl where item_id=:item_id",{item_id:this.id});
		rr.site.sql.execute_single("delete from tmarket_item_fields_f where item_id=:item_id",{item_id:this.id});
		rr.site.sql.execute_single("delete from tmarket_item_fields_i where item_id=:item_id",{item_id:this.id});
		rr.site.sql.execute_single("delete from tmarket_item_fields_il where item_id=:item_id",{item_id:this.id});
		rr.site.sql.execute_single("delete from tmarket_item_fields_s where item_id=:item_id",{item_id:this.id});
		rr.site.sql.execute_single("delete from tmarket_item_fields_sl where item_id=:item_id",{item_id:this.id});
		rr.site.sql.execute_single("delete from tmarket_item_view_levels where item_id=:item_id",{item_id:this.id});
	},

	/**
	 * Method: FetchAllFields
	 *		Загружает все характеристики
	 *		Изменяет модель
	 *		Добавляет поля:
	 *			this.fields - объект со всеми характеристиками
	 *			this.fields[n] - число / строка если это не enums и не lenums
	 *			this.fields[n] - массив строк - если это enums или lenums
	 *
	 */
	FetchAllFields:function() {
		var t=this;
		var rr=this.GetRR();
		var fd=init_field_dictionaries(rr);
		this.fields={};


		var tables={};
		var tables_l10n={};

		var done={"enums":0,"lenums":0};
		for (var gid in fd.field_groups) {// По каждой группе параметров
			var grp=fd.field_groups[gid];
			if (grp.category_id && grp.category_id!=this.category_id) continue;
			grp.fields.forEach(function(fld) {// По каждому параметру
				var dt=fd.field_datatypes[fld.datatype_id];

				if (dt.code=="lenums" || dt.code=="enums") {
					if (!t.fields[fld.id]) t.fields[fld.id]=[];
					if (!done[dt.code]) {
						var arr=rr.site.sql.execute_and_fetch("market_item_fields_"+dt.code+"/list_of_item",{item_id:t.id});
						for (var jj=0;jj<arr.length;jj++) {
							if (!t.fields[arr[jj].field_id]) t.fields[arr[jj].field_id]=[];
							t.fields[arr[jj].field_id].push(arr[jj].value);
						}
					}
					done[dt.code]=1;
					return;
				}//throw new Error("TODO");

				var table="Tmarket_item_fields_"+dt.prefix;
				var col=(grp.category_id?"fldcat":"fldany")+fld.cid;

				// Loading ALL data from exact table
				if (dt.has_l10n) {
					if (!tables_l10n[table]) {
						tables_l10n[table]={};
						rr.site.sql.execute_and_fetch_single("select * from "+table+" where item_id=:item_id",{item_id:t.id}).forEach(function(r) { tables_l10n[table][r.l10n_id]=r;});
					}
				} else {
					if (!tables[table]) {
						tables[table]=rr.site.sql.execute_and_fetch_one_single("select * from "+table+" where item_id=:item_id",{item_id:t.id});
					}
				}

				if (dt.has_l10n && dt.code!="lenum") {
					throw "TODO";
				} else {
					if (tables[table]) t.fields[fld.id]=tables[table][col];
				}

				if (dt.code=="enum" || dt.code=="lenum") t.fields[fld.id]=enum_decoder(rr,dt.has_l10n,t.fields[fld.id]);
			});
		}
	},
	/**
	 * Method: FetchOneField
	 */
	FetchOneField:function(fid) {
		var t=this;
		var rr=this.GetRR();
		var fd=init_field_dictionaries(rr);
		this.fields={};
		var tables={};
		var tables_l10n={};

		for (var gid in fd.field_groups) {
			var grp=fd.field_groups[gid];
			
			if (grp.category_id && grp.category_id!=this.category_id) continue;
			var fld;
			grp.fields.forEach(function(e) {if(e.id==fid){fld=e}});
			if (!fld)  continue;
			
			var dt=fd.field_datatypes[fld.datatype_id];

			if (dt.code=="lenums" || dt.code=="enums") throw new Error("TODO");

			var table="Tmarket_item_fields_"+dt.prefix;
			var col=(grp.category_id?"fldcat":"fldany")+fld.cid;

			// Loading ALL data from exact table
			if (dt.has_l10n) {
				if (!tables_l10n[table]) {
					tables_l10n[table]={};
					rr.site.sql.execute_and_fetch_single("select * from "+table+" where item_id=:item_id",{item_id:t.id}).forEach(function(r) { tables_l10n[table][r.l10n_id]=r;});
				}
			} else {
				if (!tables[table]) {
					tables[table]=rr.site.sql.execute_and_fetch_one_single("select * from "+table+" where item_id=:item_id",{item_id:t.id});
				}
			}

			if (dt.has_l10n && dt.code!="lenum") {
				throw "TODO";
			} else {
				if (tables[table]) t.fields[fld.id]=tables[table][col];
			}

			if (dt.code=="enum" || dt.code=="lenum") t.fields[fld.id]=enum_decoder(rr,dt.has_l10n,t.fields[fld.id]);			
		}
	},

	/**
	 * Method: SaveAllFields
	 */
	SaveAllFields: function() {
		var rr=this.GetRR();
		var fd=init_field_dictionaries(rr);
		var tables={};
		var tables_l10n={};
		var cleaned={};
		for (var k in this.fields) {
			var fld=fd.fields[k];
			var dt=fd.field_datatypes[fld.datatype_id];
			var grp=fd.field_groups[fld.group_id];
			var table="Tmarket_item_fields_"+dt.prefix;
			var col=(grp.category_id?"fldcat":"fldany")+fld.cid;
			switch (dt.code) {
				case "enum":
					var v=enum_encoder(rr,dt.has_l10n,this.fields[k],fld.id);
					if (!tables[table]) tables[table]={};
					tables[table][col]=v;
					break;
				case "lenum":
					throw new Error("TODO");
					break;
				case "lenums":
				case "enums":
					if (!cleaned[dt.code]) {
						cleaned[dt.code]=1;
						rr.site.sql.execute("market_item_fields_"+dt.code+"/delete_of_item",{item_id:this.id});
					}
					if (!this.fields[k]) break;
					for (var jj=0;jj<this.fields[k].length;jj++) {
						var v=enum_encoder(rr,dt.has_l10n,this.fields[k][jj],fld.id);
						rr.site.sql.execute("market_item_fields_"+dt.code+"/insert",{item_id:this.id,field_id:k,enum_id:v});
					}
					break;
				default:
					if (dt.has_l10n) {
						if (!tables_l10n[table]) tables_l10n[table]={};
						if (!tables_l10n[table][k]) tables_l10n[table][k]={};
						for (var l10n in this.fields[k].l10ns) {
							tables_l10n[table][k][l10n]=this.fields[k].l10ns[l10n];
						}
					} else {
						if (!tables[table]) tables[table]={};
						tables[table][col]=this.fields[k];
					}
					break;
			}
		}
		for (var tname in tables) ins_upd(this.id,rr,tname,tables[tname],0);
		for (var tname in tables_l10n) ins_upd(this.id,rr,tname,tables[k],1);


		var l10ns=[];
		var view_levels=[];
		rr.site.models.MarketViewLevel.List().forEach(function(a) {if (a.code=='no') return;view_levels.push(a.id);});
		rr.site.models.L10N.List().forEach(function(a) {l10ns.push(a.id);});
		this.CalcAllFields(view_levels,l10ns);
	},

	/**
	 * Method: ShowFields
	 */
	ShowFields: function(level_code) {
		if (!this.fields_cache) this.fields_cache={};
		var rr=this.GetRR();
		if (this.fields_cache[level_code]) return this.fields_cache[level_code];
		var a=rr.site.models.MarketItemViewLevel.List("get_use_by_code",{item_id:this.id,l10n_id:rr.site.default_l10n_id,view_level_code:level_code})[0];
		if (a) return this.fields_cache[level_code]=a.body;
		
		a=rr.site.models.MarketItemViewLevel.List("get_use_by_code",{item_id:this.id,l10n_id:rr.site.fallback_l10n_id,view_level_code:level_code})[0];
		if (a) return this.fields_cache[level_code]=a.body;
		
		return this.fields_cache[level_code]="";
	},
	/**
	 * Method: ShowField
	 */
	ShowField: function(fid) {
		this.FetchOneField(fid);
		return this.fields[fid];
	},
	/**
	 * Method: CalcAllFields
	 */
	CalcAllFields: function(view_levels,l10ns) {
		var rr=this.GetRR();
		if (!this.fields) this.FetchAllFields();
		var fd=init_field_dictionaries(rr);
		for (var k in fd.field_groups) /*if (!fd.field_groups[k].l10ns)*/ fd.field_groups[k].FetchLocales();
		for (var k in fd.fields) /*if (!fd.fields[k].l10ns)*/ fd.fields[k].FetchLocales();
		var fgs={};
		for (var j=0,sj=view_levels.length;j<sj;j++) {
			var tmp=fgs[view_levels[j]]={};
			for (var i=0,si=l10ns.length;i<si;i++) tmp[l10ns[i]]=[];
		}
	
		for (var i=0,si=fd.field_groups_by_order.length;i<si;i++) {
			var fg=fd.field_groups_by_order[i];
			for (var j=0,sj=view_levels.length;j<sj;j++)
				for (var k=0,sk=l10ns.length;k<sk;k++) fgs[view_levels[j]][l10ns[k]].push({name:fg.GetFieldInL10N("name",l10ns[k],rr.site.fallback_l10n_id),fields:[]});
			
			for (var j=0,sj=fg.fields.length;j<sj;j++) {
				var f=fg.fields[j];
//				if (!(f.id in this.fields)) continue;
				var fi=this.fields[f.id];
				if (fi==undefined || fi==null || fi==="") continue;
				if (f.view_level_id==1) continue;
				for (var k=0,sk=l10ns.length;k<sk;k++) {
					if (f.has_l10n) throw "TODO";
					var a={
						name:f.GetFieldInL10N("name",l10ns[k],rr.site.fallback_l10n_id),
						value:fi
					};
//					throw {fgs:fgs,n:f.view_level_id,l10ns_k:l10ns[k]};
					for (var n=f.view_level_id;n<5;n++) {
						fgs[n][l10ns[k]][i].fields.push(a);
					}
				}
			}
		}

		for (var j=0,sj=view_levels.length;j<sj;j++) {
			for (var i=0,si=l10ns.length;i<si;i++) {
				var vl=rr.site.models.MarketItemViewLevel.List("get_use",{item_id:this.id,l10n_id:l10ns[i],view_level_id:view_levels[j]})[0];
				if (!vl) {
					vl=rr.site.models.MarketItemViewLevel.Create();
					vl.item_id=this.id;
					vl.l10n_id=l10ns[i];
					vl.view_level_id=view_levels[j];
				}
				rr.field_groups=fgs[view_levels[j]][l10ns[i]];
				vl.body=rr.view("controllers/Market/field_cache");//vls[view_levels[j]][l10ns[i]];
				vl.SaveAll();
			}
		}
	}
}];


